from datetime import datetime, timedelta
import jwt
from flask import Blueprint, request, jsonify, current_app, g
from app.models.user import User
from app.models.mysql_db import db
from app.utils.logger import get_logger
from app.utils.decorators import require_json
from app.utils.auth import auth_required
from functools import wraps

logger = get_logger(__name__)

# 创建蓝图
auth_bp = Blueprint('auth', __name__, url_prefix='/api/auth')

@auth_bp.route('/test', methods=['GET'])
def test():
    """测试API连接的端点"""
    return jsonify({
        'status': 'success',
        'message': 'API连接成功',
        'timestamp': datetime.utcnow().isoformat()
    })

@auth_bp.route('/login', methods=['POST'])
@require_json
def login():
    """用户登录"""
    try:
        logger.info("收到登录请求")
        data = request.get_json()
        
        # 参数验证
        if not data or 'username' not in data or 'password' not in data:
            logger.warning("登录请求缺少用户名或密码")
            return jsonify({'code': 400, 'message': '缺少用户名或密码'}), 400
            
        username = data['username']
        password = data['password']
        
        logger.info(f"尝试登录: 用户名={username}")
        
        # 查询用户
        user = User.query.filter_by(username=username).first()
        
        if not user:
            logger.warning(f"用户不存在: {username}")
            return jsonify({'code': 401, 'message': '用户名或密码错误'}), 401
            
        # 记录密码格式信息
        is_hashed = user.password.startswith('pbkdf2:sha256:')
        logger.info(f"用户 {username} 的密码是{'哈希格式' if is_hashed else '明文格式'}")
        logger.info(f"密码长度: {len(user.password)}")
        logger.info(f"密码前20个字符: {user.password[:20]}...")
        
        # 尝试验证密码
        password_correct = user.check_password(password)
        logger.info(f"密码验证结果: {'成功' if password_correct else '失败'}")
        
        if not password_correct:
            return jsonify({'code': 401, 'message': '用户名或密码错误'}), 401
            
        # 生成令牌
        token_expires_in = 86400 * 7  # 7天有效期
        payload = {
            'sub': user.id,
            'username': user.username,
            'role': user.role,
            'exp': datetime.utcnow() + timedelta(seconds=token_expires_in)
        }
        
        token = jwt.encode(
            payload=payload,
            key=current_app.config['SECRET_KEY'],
            algorithm="HS256"
        )
        
        # 处理Python版本差异
        if isinstance(token, bytes):
            token = token.decode('utf-8')
            
        # 更新最后登录时间
        user.last_login = datetime.utcnow()
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'message': '登录成功',
            'data': {
                'token': token,
                'expiresIn': token_expires_in,
                'userInfo': {
                    'id': user.id,
                    'username': user.username,
                    'nickname': user.nickname,
                    'role': user.role
                }
            }
        })
        
    except Exception as e:
        logger.error(f"登录异常: {str(e)}")
        return jsonify({'code': 500, 'message': f'服务器错误: {str(e)}'}), 500

@auth_bp.route('/register', methods=['POST'])
@require_json
def register():
    """用户注册"""
    try:
        data = request.get_json()
        
        # 参数验证
        required_fields = ['username', 'email', 'password']
        for field in required_fields:
            if field not in data:
                return jsonify({"code": 400, "message": f"缺少必要字段: {field}"}), 400
        
        username = data['username']
        email = data['email']
        password = data['password']
        
        # 检查用户名是否已存在
        if User.query.filter_by(username=username).first():
            return jsonify({"code": 400, "message": "用户名已存在"}), 400
            
        # 检查邮箱是否已存在
        if User.query.filter_by(email=email).first():
            return jsonify({"code": 400, "message": "邮箱已被使用"}), 400
            
        # 创建新用户
        nickname = data.get('nickname', username)
        user = User(
            username=username,
            email=email,
            nickname=nickname,
            role='user'
        )
        user.set_password(password)
        
        db.session.add(user)
        db.session.commit()
        
        return jsonify({
            "code": 200,
            "message": "注册成功",
            "data": {
                "userId": user.id,
                "username": user.username
            }
        })
        
    except Exception as e:
        logger.error(f"注册异常: {str(e)}")
        db.session.rollback()
        return jsonify({"code": 500, "message": f"服务器错误: {str(e)}"}), 500

@auth_bp.route('/info', methods=['GET'])
@auth_required
def get_user_info():
    """获取当前登录用户信息"""
    try:
        user_id = g.user_id
        
        user = User.query.get(user_id)
        if not user:
            return jsonify({'code': 404, 'message': '用户不存在'}), 404
            
        return jsonify({
            'code': 200,
            'message': 'success',
            'data': {
                'id': user.id,
                'username': user.username,
                'email': user.email,
                'nickname': user.nickname,
                'role': user.role,
                'avatar': user.avatar,
                'lastLogin': user.last_login.isoformat() + 'Z' if user.last_login else None,     
                'createdAt': user.created_at.isoformat() + 'Z'
            }
        })
        
    except Exception as e:
        logger.error(f"获取用户信息异常: {str(e)}")
        return jsonify({'code': 500, 'message': f'服务器错误: {str(e)}'}), 500

@auth_bp.route('/change-password', methods=['POST'])
@require_json
@auth_required
def change_password():
    """修改密码"""
    try:
        data = request.get_json()
        
        # 参数验证
        if not data or 'oldPassword' not in data or 'newPassword' not in data:
            return jsonify({'code': 400, 'message': '缺少旧密码或新密码'}), 400
            
        old_password = data['oldPassword']
        new_password = data['newPassword']
        
        # 获取当前用户
        user_id = g.user_id
        user = User.query.get(user_id)
        
        if not user:
            return jsonify({'code': 404, 'message': '用户不存在'}), 404
            
        # 验证旧密码
        if not user.check_password(old_password):
            return jsonify({'code': 400, 'message': '旧密码错误'}), 400
            
        # 设置新密码
        user.set_password(new_password)
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'message': '密码修改成功'
        })
        
    except Exception as e:
        logger.error(f"修改密码异常: {str(e)}")
        return jsonify({'code': 500, 'message': f'服务器错误: {str(e)}'}), 500

@auth_bp.route('/status', methods=['GET'])
def api_status():
    """返回API状态信息，包括是否需要认证"""
    # 检查是否有认证头
    auth_header = request.headers.get('Authorization')
    auth_status = {
        'authenticated': False,
        'token_present': bool(auth_header),
        'token_format': 'unknown'
    }
    
    if auth_header:
        if auth_header.startswith('Bearer '):
            auth_status['token_format'] = 'Bearer'
            token = auth_header.split(' ')[1]
            try:
                # 尝试解码但不验证，仅检查格式
                payload = jwt.decode(
                    token,
                    options={"verify_signature": False}
                )
                auth_status['token_payload'] = {
                    'sub': payload.get('sub'),
                    'exp': payload.get('exp'),
                    'iat': payload.get('iat', None)
                }
                
                # 检查令牌是否过期
                expiry = datetime.fromtimestamp(payload.get('exp')) if payload.get('exp') else None
                if expiry:
                    auth_status['token_expired'] = expiry < datetime.utcnow()
                    auth_status['expires_at'] = expiry.isoformat()
                    
            except Exception as e:
                auth_status['token_error'] = str(e)
        else:
            auth_status['token_format'] = 'unknown'
    
    return jsonify({
        'status': 'success',
        'api_version': '1.0.0',
        'server_time': datetime.utcnow().isoformat(),
        'authentication': auth_status
    })